package main

import (
	"fmt"
	"reflect"
)

type Person struct {
	Name string
	Age  int
}

func (person Person) String() string {
	return fmt.Sprintf("name:%s , age:%d", person.Name, person.Age)
}

// 通过反射获取数据类型
func testStruct(i interface{}) {
	refType := reflect.TypeOf(i)
	fmt.Println("refType:", refType) // 这反射的是reflect.Type

	// 获取是类别
	refTypeKind := refType.Kind()
	fmt.Println("refTypeKind:", refTypeKind) // 输出refTypeKind: struct

	refValue := reflect.ValueOf(i)
	fmt.Println("refValue:", refValue)

	// 通过反射转成空接口
	convertInterface := refValue.Interface()
	// 类型断言
	person, flag := convertInterface.(Person)
	if flag {
		fmt.Println(person)
	}
}

func SetStructValue(obj interface{}, fieldName string, value interface{}) error {
	// 获取反射
	refValue := reflect.ValueOf(obj).Elem()

	if refValue.Kind() != reflect.Struct {
		return fmt.Errorf("obj is not a struct")
	}

	field := refValue.FieldByName(fieldName)
	if !field.IsValid() {
		return fmt.Errorf("field %s is not found", fieldName)
	}

	if !field.CanSet() {
		return fmt.Errorf("cannot set %s field", fieldName)
	}

	valueRef := reflect.ValueOf(value)
	filedType := field.Type()

	if !valueRef.Type().ConvertibleTo(filedType) {
		return fmt.Errorf("value of %s is not convertible to %s", filedType, valueRef.Type())
	}

	field.Set(valueRef.Convert(filedType))

	return nil
}

func main() {
	p := Person{
		Name: "zhangsan",
		Age:  22,
	}

	err := SetStructValue(&p, "Name", "李四")
	if err != nil {
		fmt.Println("set field error ->", err)
	}

	fmt.Println("修改后的结构体: ", p)
}
